package com.darwin.darwinImage.darx
{
	import com.darwin.darwinDisplay.DarBitmapManager;
	import com.darwin.darwinDisplay.DarXBitmapData;
	import com.darwin.darwinDll.analyze.SwfAnalyze;
	import com.darwin.darwinDll.core.DllItem;
	import com.darwin.darwinImage.jpg.JPEG32;
	import com.darwin.darwinImage.swf.SWFExplorer;
	import com.darwin.darwinNameSpace.darwin;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.events.Event;
	import flash.geom.Point;
	import flash.utils.ByteArray;
	import flash.utils.Dictionary;
	import flash.utils.getTimer;
	import flash.utils.setTimeout;

	/**
	 *	DarX文件解码器 
	 * @author Roland
	 * 
	 */
	public class DarXDecoder
	{
		public function DarXDecoder()
		{
		}
		
		/**
		 *	完整解码一份darXBitmapData列表 
		 * @param darxList
		 * @param compFn 解码完成后的回调 compFn(darxList:Vector.<DarXBitmapData>):void;
		 */
		public function decodeDarXBitmapDataList(darxList:Vector.<DarXBitmapData>,compFn:Function):void
		{
			var arr:Array = [];
			for (var i:int = 0; i < darxList.length; i++) 
			{
				decodeDarXBitmapData(darxList[i],onSingleComplete);
			}
			function onSingleComplete(darx:DarXBitmapData):void
			{
				if(arr && arr.indexOf(darx) == -1)
				{
					arr.push(darx);
				}
				if(arr.length == darxList.length)
				{
					if(compFn != null)
					{
						compFn(darxList);
						compFn = null;
						arr = null
					}
				}
			}
		}
		
		/**
		 *	完整解码darXBitmapData，完成后darXBitmapData中的压缩内容将被完整解压到内存 
		 * @param darx
		 * @param compFn 解码完成后的回调 compFn(darX:DarXBitmapData):void;
		 * @return 
		 * 
		 */
		public function decodeDarXBitmapData(darx:DarXBitmapData,compFn:Function):void
		{
			if(darx.frameList == null && darx.zMapList == null)
			{
				use namespace darwin;
				var frameBytesList:Vector.<ByteArray> = darx.frameBytesList; 
				var zMapBytesList:Vector.<ByteArray> = darx.zMapBytesList;
				var haszMap:Boolean = (zMapBytesList != null);
				var frameCompleteFlag:Boolean = false;
				var zMapCompleteFlag:Boolean = false;
				if(darx.frameList == null)
				{
					darx.frameList = new Vector.<BitmapData>(frameBytesList.length);
					decodeBitmapDataList(darx.frameList,darx.frameBytesList,onFrameComplete,"jpeg32");
					if(haszMap){
						darx.zMapList = new Vector.<BitmapData>(zMapBytesList.length);
						decodeBitmapDataList(darx.zMapList,darx.zMapBytesList,onzMapComplete,"png");
					}else{
						zMapCompleteFlag = true;
					}
				}
			}else{
				if(darx.frameList[0] != null)
				{//已经有内容，直接回调
					frameCompleteFlag = true;
					zMapCompleteFlag = true;
					completeHandler();
				}else{//已经在解析，等待
					setTimeout(decodeDarXBitmapData,20,darx,compFn);
//					trace("重复解析，等待");
				}

			}
			function onFrameComplete():void
			{
				frameCompleteFlag = true;
				completeHandler();
			}
			function onzMapComplete():void
			{
				zMapCompleteFlag = true;
				completeHandler();
			}
			
			function completeHandler():void
			{
				if(zMapCompleteFlag && frameCompleteFlag)
				{
					if(compFn != null)
					{
						compFn(darx);
					}
				}
			}
		}
		
		/**
		 *	将swf文件(.swf)的二进制数据解码为DarXBitmapData列表
		 * @param swfBytes swf文件的二进制数据
		 * @param compFn 解析完成后的回调 callBack(list:Vector.<DarXBitmapData>);
		 * 
		 */
		public function decodeSwf(swfBytes:ByteArray,callBack:Function):void
		{
			var swfExplorer:SWFExplorer = new SWFExplorer();
			var classes:Array = swfExplorer.parse(swfBytes);
			var item:DllItem = new DllItem("",getTimer().toString(16));
			var swfAnalyze:SwfAnalyze = new SwfAnalyze();
			swfAnalyze.analyze(swfBytes,item,onSwfAnalyzeComplete);
			function onSwfAnalyzeComplete(item:DllItem):void
			{
				for (var i:int = 0; i < classes.length; i++) 
				{
					var className:String = classes[i];
					var clazz:Class = swfAnalyze.getData("",className) as Class;
					if(clazz)
					{
						classes[i] = {"name":className,"class":clazz};
					}
				}
				swfclasses = classes;
				decodeSwfClasses();
			}
			
			var swfclassIndex:int = 0;
			var swfclasses:Array;
			function decodeSwfClasses():void
			{
				var index:int = swfclassIndex;
				var list:Array = swfclasses;
				if(index < list.length)
				{
					var $clazz:Class = list[index]["class"];
					setTimeout(DarBitmapManager.getInstance().drawClass,1,$clazz,singleClassDecodeComplete);
				}else{
					if(callBack != null)
					{
						var vector:Vector.<DarXBitmapData> = Vector.<DarXBitmapData>(list);
						callBack(vector);
					}
				}
			}
			
			function singleClassDecodeComplete(bitmapDataArray:Array,offsetPoint:Point,framesOffsetList:Array = null):void
			{
				var darx:DarXBitmapData = new DarXBitmapData();
				darx.key = "";
				darx.subKey = swfclasses[swfclassIndex].name;
				darx.frameList = new Vector.<BitmapData>();
				darx.frameOffsetList = new Vector.<Point>();
				for (var i:int = 0; i < bitmapDataArray.length; i++) 
				{
					darx.frameList.push(bitmapDataArray[i]);
					if(framesOffsetList)
					{
						darx.frameOffsetList.push(offsetPoint.add(new Point(framesOffsetList[i].x,framesOffsetList[i].y)));
					}else{
						darx.frameOffsetList.push(offsetPoint);
					}
				}
				swfclasses[swfclassIndex] = darx;
				swfclassIndex++;
				decodeSwfClasses();
			}
		}
		

		
		
		/**
		 *	将darx文件(.darx)的二进制数据解码为DarXBitmapData列表
		 * @param bytes
		 * @param callBack 解析完成后的回调 callBack(list:Vector.<DarXBitmapData>);
		 * @param fullDecode 是否完整解析，如果为false则将只填充darxBitmapData中每帧的二进制数据，
		 * 而不会将其解析为位图，当要使用时再次调用decodeDarXBitmapData来完整解析单个DarXBitmapData。
		 * (这样可以在真正想使用此动画数据时才解码位图，而平时可以保持一个仅占用少量内存的压缩状态)
		 * @return 
		 * 
		 */
		public function decode(bytes:ByteArray,callBack:Function,fullDecode:Boolean = true):void
		{
			var dataList:Vector.<DarXBitmapData> = new Vector.<DarXBitmapData>();
			bytes.uncompress();
			bytes.position = 0;
			decodeObj(bytes.readObject(),decodeObjComplete,fullDecode);
			function decodeObjComplete(darxBitmapData:DarXBitmapData):void
			{
				dataList.push(darxBitmapData);
				if(bytes.bytesAvailable)
				{
					var darXObject:Object = bytes.readObject();
					decodeObj(darXObject,decodeObjComplete,fullDecode);
				}else{
					if(callBack != null)
					{
						callBack(dataList);
					}
				}
			}
		}
		
		/**
		 *	解析darXObject对象 
		 * @param darXObject 
		 * @param callBack 回调 callBack(DarXBitmapData);
		 * @param fullDecode 是否完全解析
		 */
		private function decodeObj(darXObject:Object,callBack:Function,fullDecode:Boolean):void
		{
			use namespace darwin;
			var darXBitmapData:DarXBitmapData = new DarXBitmapData();
			var hasZmapArr:Boolean = darXObject.hasOwnProperty("zMapList");
			var frameArr:Array =  darXObject.frameList;
			var zMapArr:Array = hasZmapArr ? darXObject.zMapList : null;
			var offsetArr:Array =  darXObject.frameOffsetList;
			var key:String = darXObject.key;
			var subKey:String = darXObject.subKey;
			var zmapComplete:Boolean = false;
			var frameComplete:Boolean = false;
			darXBitmapData.key = key;
			darXBitmapData.subKey = subKey;
			darXBitmapData.frameOffsetList = new Vector.<Point>();
			darXBitmapData.frameBytesList = new Vector.<ByteArray>();
			if(hasZmapArr)
				darXBitmapData.zMapBytesList = new Vector.<ByteArray>();
			
			for (var i:int = 0; i < offsetArr.length; i++) 
			{
				darXBitmapData.frameOffsetList.push(new Point(offsetArr[i].x,offsetArr[i].y));
				darXBitmapData.frameBytesList.push(frameArr[i]);
				if(hasZmapArr){
					darXBitmapData.zMapBytesList.push(zMapArr[i]);
				}
			}
			
			if(fullDecode == true)
			{
				darXBitmapData.frameList = new Vector.<BitmapData>(frameArr.length);
				decodeBitmapDataList(darXBitmapData.frameList,frameArr,frameCompleteHandler,"jpeg32");
				if(hasZmapArr){
					darXBitmapData.zMapList = new Vector.<BitmapData>(zMapArr.length);
					decodeBitmapDataList(darXBitmapData.zMapList,zMapArr,zmapCompleteHander,"png");
				}else{
					zmapComplete = true;
				}
			}else{
				frameComplete = true;
				zmapComplete = true;
				completeHandler();
			}
	
			function frameCompleteHandler():void
			{
				frameComplete = true;
				completeHandler();
			}
			
			function zmapCompleteHander():void
			{
				zmapComplete = true;
				completeHandler();
			}
			
			function completeHandler():void
			{
				if(frameComplete && zmapComplete)
				{
					if(callBack != null)
					{
						callBack(darXBitmapData);
					}
				}
			}
		}
		
		/**
		 *	将ByteArray解析为bitmapData并放入targetList的相应位置
		 * @param targetList 目标列表 ，解析完成的数据最终会依次填入目标列表中去，长度必须和bytesArrayList相同
		 * @param bytesArrayList 原始动画帧二进制数据列表，可以是Array也可以是子项为BytesArray的Vector
		 * @param encodeType 图片编码类型("png" or "jpeg32")
		 */
		private function decodeBitmapDataList(targetList:Vector.<BitmapData>,bytesArrayList:*,completeCallBack:Function,encodeType:String):void
		{
			var count:int = 0;
			for (var i:int = 0; i < bytesArrayList.length; i++) 
			{
				var bytes:ByteArray = bytesArrayList[i];
				decodeSingle(bytes,i,setData,encodeType)
			}
			function setData(data:BitmapData,index:int):void
			{
				targetList[index] = data;
				count++;
				if(count>=targetList.length)
				{
					completeCallBack();
				}
			}
		}
		
		private function decodeSingle(bytesArray:ByteArray,index:int,setDataFun:Function,encodeType:String):void
		{
			bytesArray.position = 0;
			if(encodeType == "jpeg32")
			{
				var jpeg:JPEG32 = new JPEG32();
				jpeg.decode(bytesArray);
				jpeg.addEventListener(Event.COMPLETE,onJpegDecodeComplete);
			}else{
				var $loader:Loader = new Loader();
				$loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onLoadComplete);
				$loader.loadBytes(bytesArray);
			}
			function onJpegDecodeComplete(event:Event):void
			{
				if(event.target is JPEG32)
				{
					(event.target as JPEG32).removeEventListener(Event.COMPLETE,onJpegDecodeComplete);
					var $bitmapData:BitmapData = (event.target as JPEG32).bitmapData;
					setDataFun($bitmapData,index);
				}
			}
			function onLoadComplete(event:Event):void
			{
				$loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,onLoadComplete);
				var $bitmapData:BitmapData =  ($loader.content as Bitmap).bitmapData;
				setDataFun($bitmapData,index);
			}
		}
		
	}
}